package com.mdp.workflow.bus.listener.task;

import com.mdp.core.entity.Tips;
import com.mdp.core.err.BizException;
import com.mdp.micro.client.CallBizService;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.TaskListener;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.service.delegate.DelegateTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * 针对UserTask节点的任务监听器 ，为了能提前锁定业务数据状态，需要配置流程启动事件监听器，在流程启动时更新业务数据状态为审核中，以便锁定业务状态
 * 
 * 流程定义时：
 * 在人工任务节点上配置 任务监听器  建议事件为 complete,其它assignment/create/complete/delete也可以，一般建议在complete,委托代理表达式 ${taskBizCallListener}
 * 必须填写一个字段   字段名 restUrl,字符串值: 填写具体的回调地址，可带参数，类似普通的url地址
 * 
 * 发起流程时上送业务主键： bizKey，用于业务系统判断是否正确的回调，防止用错流程发起审批，回调更新错误数据。回调时将原样返回。回调时同时返回 agree,procInstId,assignee,actId,taskName,mainTitle,flowBranchId,bizKey,commentMsg,eventName 10个变量，以及在监听器中配置的其它变量
 * 
 * 发起流程时 提交给工作流的流程变量如下
 * 
 * bizUrl 为 跳转页面地址，可带参数，url编码
 * flowVars 提交给流程实例的变量对象，如 flowVars={field1:fieldValue1,field2:fieldValue2,field3:fieldValue3等等任意变量名及值}，flowVars也会按参数形式通过restUrl返回
 * 
 * 举例： 
 * 流程模型中配置 restUrl: wwww.qqkj.cn/api/m1/sys/sys/opencompany?companyId=xxx
 * 
 * 发起流程时：
 * 
 * {
 * 	bizUrl: wwww.qqkj.cn/#/sys/sys/m1/opencompany?companyId=xxx
 *  flowVars:{vipLvl:vip1,createUserid: cuser1},
 *  bizKey: xxxx,
 * }
 * 
 * 流程审核时：
 * 在流程审批页面呈现  wwww.qqkj.cn/#/sys/sys/m1/opencompany?companyId=xxx，点击直接跳转到该地址
 * 
 * 流程审核提交时（同意/不同意）： 将 post方式调用  wwww.qqkj.cn/api/m1/sys/sys/opencompany?companyId=xxx, 
 * 				参数为 : {vipLvl:vip1,createUserid: cuser1,agree:'0|1',procInstId:'xxxxxxfafad',assignee:'任务提交人|审核人',actId:'当前节点编号',taskName:'',mainTitle:'',bizKey:'',flowBranchId:''}
 * 
 * @author qqkj
 *
 */
@Component(value = "taskBizCallListener")
public class TaskBizCallListener  implements TaskListener {
	
	
	@Autowired
    CallBizService callBizService;

	Expression restUrl;
	
	
	@Autowired
	RuntimeService runtimeService; 
 
    @Override
    public void notify(DelegateTask delegateTask) {
        String processInstanceId = delegateTask.getProcessInstanceId();
        Map<String, Object> paramMap = new HashMap<String, Object>();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        ///processInstance.get
        String bizKey=processInstance.getBusinessKey();
        String restUrl=(String) this.restUrl.getValue(delegateTask);
        Map<String,Object> flowVars=delegateTask.getVariables(); 
        String restUrlFromFlowVars=(String) flowVars.get("restUrl");
        if(!StringUtils.isEmpty(restUrlFromFlowVars)) {
        	restUrl=restUrlFromFlowVars;
        }
         
        String mainTitle=processInstance.getName();
        String assignee=delegateTask.getAssignee();
        String actId=delegateTask.getTaskDefinitionKey();
        String taskName=delegateTask.getName();
        String branchId=delegateTask.getTenantId();
        String eventName=delegateTask.getEventName();
        paramMap.putAll(flowVars);
        paramMap.put("procInstId", processInstanceId);
        paramMap.put("mainTitle", mainTitle);
        paramMap.put("assignee", assignee);
        paramMap.put("actId", actId);
        paramMap.put("taskName", taskName);
        paramMap.put("flowBranchId", branchId); 
        paramMap.put("bizKey", bizKey);
        paramMap.put("eventName", eventName); 
        paramMap.put("modelKey", processInstance.getProcessDefinitionId());
        //paramMap.put("commentMsg", commentMsg);//已经在flowVars中了 
        Tips tips =  callBizService.postForTips(restUrl, paramMap);
    	if(!tips.isOk()){
			throw new BizException(tips);
		}  
		
        //执行回调
    }
}